package com.xywy.beautyand.util;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.ImageView;

public class ImageLoader {

	private static final String TAG = "ImageLoader";

	private static final long CACHE_VALID_TIME = (long) 1 * 24 * 60 * 60 * 1000;
	private HashMap<String, SoftReference<Drawable>> imageRamCache;
	private String mFileCacheDir = "/mnt/sdcard/app/image_cache/";

	private BlockingQueue mQueue;
	private ThreadPoolExecutor mExecutor;

	public ImageLoader() {
		imageRamCache = new HashMap<String, SoftReference<Drawable>>();
		// �̳߳أ����50��ÿ��ִ�У�1������߳̽���ĳ�ʱʱ�䣺180��
		mQueue = new LinkedBlockingQueue();
		mExecutor = new ThreadPoolExecutor(10, 50, 180, TimeUnit.SECONDS,
				mQueue);

		File dir = new File(mFileCacheDir);
		if (!dir.exists()) {
			dir.mkdirs();
		}
		if (dir.listFiles() != null) {
			for (File tmpFile : dir.listFiles()) {
				if (System.currentTimeMillis() - tmpFile.lastModified() > CACHE_VALID_TIME) {
					tmpFile.delete();
				}
			}
		}
	}

	/**
	 * �첽����ת��ΪԲ�ǲ�����
	 * 
	 * @param imageUrl
	 * @param imageView
	 * @param imageCallback
	 * @return
	 */
	public Drawable loadDrawable(final String imageUrl,
			final ImageView imageView,

			final ImageCallback imageCallback) {
		resetPurgeTimer();
		if(imageUrl==null)
			return null;
		if (imageRamCache.containsKey(imageUrl)) {
			SoftReference<Drawable> softRef = imageRamCache.get(imageUrl);
			Drawable drawable = softRef.get();
			if (drawable != null) {
				return drawable;
			}
		}

		Drawable drawable = getImgFromFileCache(imageUrl);
		if (drawable != null) {
			return drawable;
		}

		final Handler handler = new Handler() {
			@Override
			public void handleMessage(Message msg) {
				imageCallback.imageLoaded((Drawable) msg.obj, imageView,
						imageUrl);
			}
		};

	

		 // ���̳߳�4������ͼƬ������
		mExecutor.execute(new Runnable() {
			@Override
			public void run() {
				Drawable drawable = null;
				try {
					drawable = getDrawableFromUrl(imageUrl);
				} catch (Exception e) {
					Log.e(TAG, e.getMessage(), e);
					drawable = null;
				} catch (OutOfMemoryError err) {
					Log.e(TAG, err.getMessage(), err);
					drawable = null;
				}
				if (drawable != null) {
					imageRamCache.put(imageUrl, new SoftReference<Drawable>(
							drawable));
					writeImgToSDCard(imageUrl, drawable);
				}
				Message message = handler.obtainMessage(0, drawable);
				handler.sendMessage(message);
			}
		});

		return null;
	}

	void writeImgToSDCard(String imageUrl, Drawable drawable) {
		if (android.os.Environment.getExternalStorageState().equals(
				android.os.Environment.MEDIA_MOUNTED)) {
			String filename = TextUtil.getMD5Str(imageUrl, "32");
			FileOutputStream fos = null;
			try {
				fos = new FileOutputStream(mFileCacheDir + filename);
			} catch (FileNotFoundException e1) {
				return;
			}
			((BitmapDrawable) drawable).getBitmap().compress(
					Bitmap.CompressFormat.PNG, 100, fos);
			try {
				fos.flush();
			} catch (IOException e) {
				e.printStackTrace();
			}
			try {
				fos.close();
			} catch (IOException e) {
				e.printStackTrace();
			}

		}

	}

	public Drawable getImgFromFileCache(String imageUrl) {
		if (imageUrl == null) {
			return null;
		}
		if (android.os.Environment.getExternalStorageState().equals(
				android.os.Environment.MEDIA_MOUNTED)) {
			Bitmap bitmap = null;
			try {
				bitmap = BitmapFactory.decodeFile(mFileCacheDir
						+ TextUtil.getMD5Str(imageUrl, "32"));
			} catch (OutOfMemoryError err) {
				BitmapFactory.Options opts = new BitmapFactory.Options();
				opts.inSampleSize = 2;
				try {
					bitmap = BitmapFactory.decodeFile(
							mFileCacheDir + TextUtil.getMD5Str(imageUrl, "32"),
							opts);
				} catch (OutOfMemoryError err2) {

				}
			}
			if (bitmap == null) {
				return null;
			}
			Drawable drawable = new BitmapDrawable(bitmap);
			imageRamCache.put(imageUrl, new SoftReference<Drawable>(drawable));
			return drawable;
		}
		return null;
	}

	Drawable getDrawableFromUrl(String url) throws Exception {
		byte[] bytes = getBytesFromUrl(url);
		if (bytes == null)
			return null;
		BitmapDrawable bitmapDrawable = (BitmapDrawable) byteToDrawable(bytes);
		return bitmapDrawable;
	}

	byte[] getBytesFromUrl(String url) throws Exception {
		return readInputStream(getRequest(url));
	}

	Drawable byteToDrawable(byte[] byteArray) {
		ByteArrayInputStream ins = new ByteArrayInputStream(byteArray);
		return Drawable.createFromStream(ins, null);
	}

	 BitmapDrawable toRoundCorner(BitmapDrawable bitmapDrawable, int pixels) {
	 Bitmap bitmap = bitmapDrawable.getBitmap();
	 // bitmapDrawable = new BitmapDrawable(bitmap);
	 bitmapDrawable = new BitmapDrawable(toRoundCorner(bitmap, pixels));
	 return bitmapDrawable;
	 }

	Bitmap toRoundCorner(Bitmap bitmap, int pixels) {

		Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
				bitmap.getHeight(), Config.ARGB_8888);
		Canvas canvas = new Canvas(output);

		final int color = 0xff424242;
		final Paint paint = new Paint();
		final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
		final RectF rectF = new RectF(rect);
		final float roundPx = pixels;

		paint.setAntiAlias(true);
		canvas.drawARGB(0, 0, 0, 0);
		paint.setColor(color);
		canvas.drawRoundRect(rectF, roundPx, roundPx, paint);

		paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
		canvas.drawBitmap(bitmap, rect, rect, paint);

		return output;
	}

	InputStream getRequest(String path) throws Exception {
		if (path == null || path.trim().equals("")) {
			return null;
		}
		try {
			URL url = new URL(path);
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			conn.setRequestMethod("GET");
			conn.setConnectTimeout(5000);
			if (conn.getResponseCode() == 200) {
				return conn.getInputStream();
			}
		} catch (Exception e) {
			return null;
		}
		return null;
	}

	byte[] readInputStream(InputStream inStream) throws Exception {

		if (inStream == null)
			return null;
		ByteArrayOutputStream outStream = new ByteArrayOutputStream();
		byte[] buffer = new byte[4096];
		int len = 0;
		while ((len = inStream.read(buffer)) != -1) {
			outStream.write(buffer, 0, len);
		}
		outStream.close();
		inStream.close();
		return outStream.toByteArray();
	}

	public interface ImageCallback {
		public void imageLoaded(Drawable imageDrawable, ImageView imageView,
				String imageUrl);
	}
	
	private final Handler purgeHandler = new Handler();

	private final Runnable purger = new Runnable() {
		public void run() {
			clearCache();
		}
	};
	/**
	 * Clears the image cache used internally to improve performance. Note that
	 * for memory efficiency reasons, the cache will automatically be cleared
	 * after a certain inactivity delay.
	 */
	public void clearCache() {
		imageRamCache.clear();
	}

	/**
	 * Allow a new delay before the automatic cache clear is done.
	 */
	private void resetPurgeTimer() {
		purgeHandler.removeCallbacks(purger);
		purgeHandler.postDelayed(purger, 10000);
	}
}
